home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Amiga Format CD 43
/
Amiga Format CD43 (1999)(Future Publishing)(GB)(Track 1 of 2)[!][issue 1999-09].iso
/
-serious-
/
archivers
/
xpk
/
xpk_source
/
xpkmaster
/
password.c
< prev
next >
Wrap
C/C++ Source or Header
|
1999-06-14
|
13KB
|
469 lines
#ifndef XPKMASTER_PASSWORD_C
#define XPKMASTER_PASSWORD_C
/* Routinesheader
Name: password.c
Main: xpkmaster
Versionstring: $VER: password.c 1.13 (27.03.1998)
Author: SDI
Distribution: Freeware
Description: password requester related things
1.0 27.12.96 : first version
1.1 28.12.96 : starting to code the stuff
1.2 29.12.96 : optimized and removed bugs
1.3 02.01.97 : corrected return handling
1.4 01.03.97 : fixed tag parsing error
1.5 10.04.97 : now old screen comes to front after Request
1.6 15.10.97 : TimeOut now uses timer.device
1.7 07.11.97 : timout of 0 again means no timeout
1.8 27.12.97 : added title line to passrequest
1.9 09.01.98 : gadget uses gadtools now
1.10 18.01.98 : added 5 position tags
1.11 21.01.98 : added verification mode
1.12 21.02.98 : uses new style register definition
1.13 27.03.98 : some optimizations
*/
#include <proto/intuition.h>
#include <proto/exec.h>
#include <proto/utility.h>
#include <proto/gadtools.h>
#include <exec/memory.h>
#include <exec/errors.h>
#include <intuition/sghooks.h>
#include <intuition/intuitionbase.h>
#include <intuition/gadgetclass.h>
#include <xpk/xpk.h>
#include <xpk/xpkprefs.h>
#include "texts.h"
#include "xpkmaster.h"
#define TESTSIZE 13
#define VERIFY_OFF 0
#define VERIFY_ON 1
#define VERIFY_ACTIVE 2
#define VERIFY_DONE 3
static const struct PassCharData {
ULONG Flag;
UBYTE Lower;
UBYTE Upper;
} TestField[TESTSIZE] = {
{XPKPASSFF_30x39,0x30,0x39}, {XPKPASSFF_41x46,0x41,0x46},
{XPKPASSFF_61x66,0x61,0x66}, {XPKPASSFF_47x5A,0x47,0x5A},
{XPKPASSFF_67x7A,0x67,0x7A}, {XPKPASSFF_20, 0x20,0x20},
{XPKPASSFF_SPECIAL7BIT,0x21,0x2F},
{XPKPASSFF_SPECIAL7BIT,0x3A,0x40},
{XPKPASSFF_SPECIAL7BIT,0x5B,0x60},
{XPKPASSFF_SPECIAL7BIT,0x7B,0x7E},
{XPKPASSFF_C0xDE,0xC0,0xDE}, {XPKPASSFF_DFxFF,0xDF,0xFF},
{XPKPASSFF_SPECIAL8BIT,0xA0,0xBF},
};
/* this is no public structure !! */
struct RequestData {
ULONG rd_Time;
ULONG rd_GadgFlags;
ULONG rd_BufSize;
WORD rd_WinLeft;
WORD rd_WinTop;
WORD rd_WinWidth;
WORD rd_WinHeight;
UWORD rd_WinCenter;
UWORD rd_Verify;
STRPTR rd_Title;
STRPTR rd_GivenBuffer;
struct Window * rd_Window;
struct Screen * rd_GivenScreen;
struct Screen * rd_FirstScreen;
struct timerequest * rd_TimeRequest;
STRPTR rd_PassBuffer;
UBYTE rd_ScreenTitle[80];
UBYTE rd_KeyBuffer[9];
};
static void SendTimerReq(struct RequestData *rd)
{
rd->rd_TimeRequest->tr_node.io_Command = TR_ADDREQUEST;
rd->rd_TimeRequest->tr_time.tv_secs = rd->rd_Time;
SendIO((struct IORequest *) rd->rd_TimeRequest);
}
static ASM(ULONG) PassHookFunc(REG(a0, struct Hook *hook),
REG(a2, struct SGWork *sgw), REG(a1, ULONG *msg))
{
struct RequestData *rd;
rd = (struct RequestData *) sgw->Gadget->UserData;
if(rd->rd_Time)
AbortIO((struct IORequest *) rd->rd_TimeRequest);
if(*msg == SGH_KEY)
{
STRPTR passbuf = rd->rd_PassBuffer;
ULONG bufpos = sgw->BufferPos-1;
STRPTR wbuf = sgw->WorkBuffer;
switch(sgw->EditOp)
{
case EO_INSERTCHAR:
{
register UBYTE c = sgw->Code;
if(rd->rd_Verify == VERIFY_ACTIVE)
{
if(c != passbuf[bufpos])
{
sgw->Actions |= SGA_BEEP; /* let the screen beep */
sgw->Actions &= ~SGA_USE; /* do not use char */
}
else
wbuf[bufpos] = '*';
}
else
{
register ULONG i;
for(i = 0; i < TESTSIZE; ++i)
{
if((rd->rd_GadgFlags & TestField[i].Flag) &&
(c >= TestField[i].Lower) && (c <= TestField[i].Upper))
break;
}
if(i == TESTSIZE)
{
sgw->Actions |= SGA_BEEP; /* let the screen beep */
sgw->Actions &= ~SGA_USE; /* do not use char */
}
else
{
passbuf[bufpos] = c;
passbuf[sgw->NumChars] = 0;
wbuf[bufpos] = '*';
}
}
}
break;
case EO_CLEAR:
if(rd->rd_Verify != VERIFY_ACTIVE)
*passbuf = 0;
*wbuf = 0;
sgw->NumChars = sgw->BufferPos = 0;
sgw->EditOp = EO_BIGCHANGE;
break;
case EO_DELBACKWARD:
if(rd->rd_Verify != VERIFY_ACTIVE)
passbuf[sgw->NumChars] = 0;
break;
case EO_ENTER:
if(rd->rd_Verify == VERIFY_ON && sgw->NumChars)
{
SetWindowTitles(rd->rd_Window, strings[TXT_VERIFY_PASS], (STRPTR) ~0);
rd->rd_Verify = VERIFY_ACTIVE;
*wbuf = 0;
sgw->NumChars = sgw->BufferPos = 0;
sgw->EditOp = EO_BIGCHANGE;
sgw->Actions &= ~SGA_END;
}
else if(rd->rd_Verify == VERIFY_ACTIVE && !passbuf[sgw->NumChars])
rd->rd_Verify = VERIFY_DONE;
case EO_NOOP:
break;
/* prevent to complicated edit operations, like cursor move */
default:
sgw->Actions &= ~SGA_USE;
sgw->Actions |= SGA_BEEP;
break;
} /* switch */
return ~0;
}
else if(*msg == SGH_CLICK) /* on click set last character */
{
sgw->BufferPos = sgw->NumChars;
sgw->EditOp = EO_BIGCHANGE;
}
else
return 0;
}
static struct Hook PassHook = { {0}, (ULONG (*) ()) PassHookFunc, 0, 0};
/* returns XPKERR codes */
static LONG DoRequest(struct RequestData *rd)
{
struct Screen *scr;
struct MsgPort *MsgPort = 0;
LONG err = XPKERR_UNKNOWN;
if(rd->rd_GivenScreen)
scr = rd->rd_GivenScreen;
else if(!(scr = LockPubScreen(0)))
return XPKERR_UNKNOWN;
*rd->rd_PassBuffer = 0;
if(!rd->rd_Time || (MsgPort = CreateMsgPort()))
{
ULONG tflag = rd->rd_Time ? 1 << MsgPort->mp_SigBit : 0;
if(!tflag || (rd->rd_TimeRequest = (struct timerequest *)
CreateIORequest(MsgPort, sizeof(struct timerequest))))
{
if(!tflag || !OpenDevice("timer.device",UNIT_VBLANK,
(struct IORequest *) rd->rd_TimeRequest,0))
{
APTR vi;
if((vi = GetVisualInfoA(scr, 0)))
{
struct Gadget *gadg, *gl = 0;
struct NewGadget ng;
ULONG i;
i = 4 + scr->WBorLeft + scr->WBorRight;
if(rd->rd_WinWidth < i + 50)
rd->rd_WinWidth = scr->Width >> 1;
if(rd->rd_WinWidth > scr->Width)
rd->rd_WinWidth = scr->Width;
ng.ng_Width = rd->rd_WinWidth - i;
i = 4 + scr->WBorTop + scr->Font->ta_YSize + 1 + scr->WBorBottom;
if(rd->rd_WinHeight < i + scr->Font->ta_YSize + 6)
rd->rd_WinHeight = i + scr->Font->ta_YSize + 6;
if(rd->rd_WinHeight > scr->Height)
rd->rd_WinHeight = scr->Height;
ng.ng_Height = rd->rd_WinHeight - i;
ng.ng_TopEdge = scr->WBorTop + scr->Font->ta_YSize + 1 + 2;
ng.ng_LeftEdge = scr->WBorLeft + 2;
ng.ng_GadgetText = 0;
ng.ng_TextAttr = scr->Font;
/* ng.ng_GadgetID is not used --> not initialized */
ng.ng_Flags = 0;
ng.ng_VisualInfo = vi;
ng.ng_UserData = rd;
if(rd->rd_WinLeft < 0)
rd->rd_WinLeft = (scr->Width - rd->rd_WinWidth) >> 1;
else if(rd->rd_WinCenter)
rd->rd_WinLeft -= (rd->rd_WinWidth >> 1);
if(rd->rd_WinTop < 0)
rd->rd_WinTop = (scr->Height - rd->rd_WinHeight) >> 1;
else if(rd->rd_WinCenter)
rd->rd_WinTop -= (rd->rd_WinHeight >> 1);
if(rd->rd_WinTop < 0)
rd->rd_WinTop = 0;
if(rd->rd_WinLeft < 0)
rd->rd_WinLeft = 0;
if((gadg = CreateContext(&gl)) && (gadg = CreateGadget(
STRING_KIND, gadg, &ng,
GTST_EditHook, &PassHook,
STRINGA_Justification, GACT_STRINGCENTER,
GTST_MaxChars, rd->rd_BufSize-1,
TAG_DONE)))
{
struct Window *window;
if((rd->rd_Window = window = OpenWindowTags(0,
WA_Left, rd->rd_WinLeft,
WA_Top, rd->rd_WinTop,
WA_Height, rd->rd_WinHeight,
WA_Width, rd->rd_WinWidth,
WA_Gadgets, gl,
WA_IDCMP, IDCMP_GADGETUP|IDCMP_ACTIVEWINDOW|IDCMP_CLOSEWINDOW,
WA_Flags, WFLG_DRAGBAR|WFLG_DEPTHGADGET|WFLG_ACTIVATE|
WFLG_RMBTRAP|WFLG_CLOSEGADGET,
WA_Title, rd->rd_Title,
WA_PubScreen, scr,
WA_AutoAdjust, TRUE,
WA_PubScreenFallBack, TRUE, TAG_DONE)))
{
struct IntuiMessage *msg;
BOOL stop = 0;
rd->rd_FirstScreen = IntuitionBase->FirstScreen;
ScreenToFront(scr);
if(tflag)
SendTimerReq(rd);
while(!stop)
{
if((i = Wait((1<<window->UserPort->mp_SigBit)|tflag)) & tflag)
{ /* when tflag is zero, this is never reached */
if(rd->rd_TimeRequest->tr_node.io_Error == IOERR_ABORTED)
SendTimerReq(rd); /* got aborted, resend */
else
stop = 20;
}
if(i & (1 << window->UserPort->mp_SigBit))
{
while(!stop && (msg = (struct IntuiMessage *)
GetMsg(window->UserPort)))
{
if(msg->Class == IDCMP_ACTIVEWINDOW)
ActivateGadget(gadg, window, 0);
else if(msg->Class == IDCMP_CLOSEWINDOW)
stop = 10;
else /* if(msg->Class == IDCMP_GADGETUP) */
stop = 1;
ReplyMsg((struct Message *) msg);
}
}
}
if(stop >= 20)
err = XPKERR_REQTIMEOUT;
else if(rd->rd_Verify == VERIFY_ACTIVE)
err = XPKERR_WRONGPW;
else if(stop >= 10 || !*rd->rd_PassBuffer)
err = XPKERR_ABORTED;
else
err = XPKERR_OK;
if(tflag)
{
AbortIO((struct IORequest *) rd->rd_TimeRequest);
WaitIO((struct IORequest *) rd->rd_TimeRequest);
}
}
CloseWindow(window);
if(rd->rd_FirstScreen != scr) /* possibly dangerous routine */
{
struct Screen *sc;
Forbid();
sc = IntuitionBase->FirstScreen;
while((sc = sc->NextScreen) && sc != rd->rd_FirstScreen)
;
if(sc)
ScreenToFront(sc);
Permit();
}
}
if(gl)
FreeGadgets(gl);
FreeVisualInfo(vi);
}
if(tflag)
CloseDevice((struct IORequest *) rd->rd_TimeRequest);
}
if(rd->rd_TimeRequest)
DeleteIORequest(rd->rd_TimeRequest);
}
if(MsgPort)
DeleteMsgPort(MsgPort);
}
if(!rd->rd_GivenScreen)
UnlockPubScreen(0, scr);
return err;
}
ASM(LONG) LIBXpkPassRequest(REG(a0, struct TagItem *ti))
{
register struct RequestData *rd;
LONG mode = 0, useprefs = 1;
struct TagItem *tags = ti;
#ifdef DEBUG
DebugTagList("XpkPassRequest", tags);
#endif
if(!(rd = (struct RequestData *) AllocMem(sizeof(struct RequestData),
MEMF_PUBLIC|MEMF_CLEAR)))
return XPKERR_NOMEM;
/* set defaults */
rd->rd_Time = 120;
rd->rd_GadgFlags = XPKPASSFLG_PRINTABLE;
rd->rd_WinLeft = rd->rd_WinTop = -1;
while((ti = NextTagItem(&tags)))
{
switch(ti->ti_Tag)
{
case XPK_PassChars: rd->rd_GadgFlags = ti->ti_Data; break;
case XPK_PasswordBuf:
rd->rd_GivenBuffer = (STRPTR) ti->ti_Data; mode += 10; break;
case XPK_PassBufSize: rd->rd_BufSize = ti->ti_Data; break;
case XPK_Key16BitPtr:
rd->rd_GivenBuffer = (STRPTR) ti->ti_Data; mode += 11; break;
case XPK_Key32BitPtr:
rd->rd_GivenBuffer = (STRPTR) ti->ti_Data; mode += 12; break;
case XPK_PubScreen: rd->rd_GivenScreen = (struct Screen *) ti->ti_Data; break;
case XPK_PassTitle: rd->rd_Title = ti->ti_Data ? (STRPTR) ti->ti_Data : ""; break;
case XPK_TimeOut: useprefs = 0; rd->rd_Time = ti->ti_Data; break;
case XPK_Preferences: if(!ti->ti_Data) useprefs = 0; break;
case XPK_PassWinLeft: rd->rd_WinLeft = ti->ti_Data; break;
case XPK_PassWinTop: rd->rd_WinTop = ti->ti_Data; break;
case XPK_PassWinWidth: rd->rd_WinWidth = ti->ti_Data; break;
case XPK_PassWinHeight: rd->rd_WinHeight = ti->ti_Data; break;
case XPK_PassCenter: rd->rd_WinCenter = ti->ti_Data; break;
case XPK_PassVerify:
rd->rd_Verify = (ti->ti_Data ? VERIFY_ON : VERIFY_OFF); break;
};
}
if(!mode || (mode > 12) || (mode == 10 && !rd->rd_BufSize) ||
!rd->rd_GivenBuffer)
{
FreeMem(rd, sizeof(struct RequestData));
return XPKERR_BADPARAMS;
}
if(useprefs) /* call the preferences */
{
struct XpkPrefsSemaphore *sem;
if((sem = GetPrefsSem()))
{
if(sem->xps_MainPrefs)
rd->rd_Time = sem->xps_MainPrefs->xmp_Timeout;
ReleaseSemaphore((struct SignalSemaphore *) sem);
}
}
if(!rd->rd_Title) /* create title text */
{
if(mode == 10)
rd->rd_Title = strings[TXT_REQ_PASSWORD];
else
{
rd->rd_Title = rd->rd_ScreenTitle;
sprintf(rd->rd_ScreenTitle, strings[TXT_REQ_KEY], (mode == 11 ? 16 : 32));
}
}
if(mode > 10)
{
rd->rd_BufSize = (mode == 11 ? 5 : 9);
rd->rd_PassBuffer = rd->rd_KeyBuffer;
rd->rd_GadgFlags = XPKPASSFLG_HEXADECIMAL;
}
else
rd->rd_PassBuffer = rd->rd_GivenBuffer;
if(!(useprefs = DoRequest(rd)))
{
if(mode == 11)
*((UWORD *) rd->rd_GivenBuffer) = strtoul(rd->rd_PassBuffer, 0, 16);
else if(mode == 12)
*((ULONG *) rd->rd_GivenBuffer) = strtoul(rd->rd_PassBuffer, 0, 16);
}
FreeMem(rd, sizeof(struct RequestData));
return useprefs;
}
#endif /* XPKMASTER_PASSWORD_C */